/**
 * FssCommandLineUI.java
 */
package fss.client.ui;

import java.io.File;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import fss.client.FileServiceClientUI;
import fss.client.FssCommandLineClient;
import fss.common.communication.DownloadRequest;
import fss.common.communication.QueryResult;
import fss.common.communication.UploadRequest;
import fss.remote.util.RemoteFileService;
import fss.transfer.Transfer;
import fss.transfer.TransferId;
import fss.transfer.TransferSource;
import fss.transfer.TransferType;
import fss.transfer.TransferUtils;
import fss.util.FssUtils;
import fss.util.rmi.RmiId;
import fss.util.rmi.RmiUtils;

/**
 * A command line user interface to interact with the entire
 * File Service system.
 * 
 * @author thinh
 *
 */
public class FssCommandLineUI implements FileServiceClientUI {
    /**
     * The object that this driver uses.
     */
    private FssCommandLineClient client = null;
    /**
     * The RMI registry where the client resides.
     */
    private Registry rmi = null;
    /**
     * The client identifier.
     */
    private RmiId clientId = null;
    /**
     * Constrcutor to instantiate this UI class.
     * @param id the client id.
     * @throws RemoteException
     */
    public FssCommandLineUI(RmiId id) throws RemoteException {
        client = new FssCommandLineClient(id);
        rmi = RmiUtils.exportFssCommandLineClient(client);
        // invoke the client rather than from 'id' as a final 
        // check to confirm that the object is good in RMI
        clientId = client.getId();
    }
    /**
     * Unbind the remote client and ignore exceptions.
     */
    public void unbind() {
        if(rmi != null) {
            try {
                rmi.unbind(clientId.getName());
            } catch (Exception e) {}
        }
    }
    @Override
    public void download() {
        System.out.println();
        Scanner in = new Scanner(System.in);
        DownloadRequest request = null;
        
        RmiId serviceId = FssUtils.getRmiId("-- Remote File Service Identifier --");
        RemoteFileService service = (RemoteFileService)RmiUtils.getRemoteObject(serviceId);
        System.out.println();
        List<QueryResult> files;
        try {
            files = service.getFileList();
            System.out.println("File(s) on " + serviceId);
            for(int i = 0; i < files.size(); i++) {
                System.out.println((i+1) + "." + files.get(i));
            }
            
            System.out.println();
            System.out.print("Enter the exact filename: ");
            String filename = in.nextLine();
            /*
             * It is important to note source and destination of the Download Transfer.
             * Source = Service
             * Destination = Client
             * 
             * It is reversed for an Upload Transfer.
             */
            TransferId transferId = new TransferId(TransferType.DOWNLOAD, serviceId, client.getId(),filename, TransferSource.CLIENT);
            request = new DownloadRequest(client.getId(), transferId);
            service.processRequest(request);
        } catch (RemoteException e) {
            System.err.println("Error issuing Download Request to " + serviceId + ": " + e);
        }
    }

    @Override
    public void upload() {
        Scanner in = new Scanner(System.in);
        System.out.println();
        RmiId serviceId = FssUtils.getRmiId("-- Upload Destination (File Service Identifer) --");
        System.out.println();
        List<File> files = getLocalFileList();
        System.out.println("Local File(s) on " + clientId +"(" + files.size() + ")");
        for(int i = 0; i < files.size(); i++) {
            System.out.println("" + (i+1) + ". " + files.get(i).getName());
        }
        System.out.print("Enter the exact filename: ");
        String filename = in.nextLine();
        try {
            RemoteFileService service = (RemoteFileService)RmiUtils.getRemoteObject(serviceId);
            /*
             * The client must register with the service for upload
             */
            service.register(client);
            /*
             * It is important to note source and destination of the Upload Transfer.
             * Source = Client
             * Destination = Service
             * 
             * It is reversed for a Downlaod Transfer.
             */
            TransferId transferId = new TransferId(TransferType.UPLOAD, client.getId(), serviceId,filename, TransferSource.SERVICE);
            UploadRequest request = new UploadRequest(client.getId(), transferId);
            service.processRequest(request);
        } catch (RemoteException e) {
            e.printStackTrace();
            System.err.println("Cannot complete upload transfer: " + e);
        }
    }
    @Override
    public void connect() {
        // TODO Auto-generated method stub
    }
    @Override
    public void query() {
        System.out.println();
        Scanner in = new java.util.Scanner(System.in);
        RmiId registryId = FssUtils.getRmiId("-- Remote Registry Identifier --");
        System.out.print("Enter query string: ");
        String param = in.nextLine();
        
        List<QueryResult> results = new ArrayList<QueryResult>();;
        try {
            results = client.query(registryId, param);
            System.out.println();
            System.out.println("Query results");
            int count = 1;
            for(QueryResult r : results) {
                System.out.println((count++) + ". " + r);
            }
        } catch (RemoteException e) {
            System.err.println("Error invoking query command: " + e);
        }
    }
    @Override
    public List<Transfer> getIncompleteTransferList() {
        List<Transfer> incomplete = new ArrayList<Transfer>();
        try {
            incomplete = TransferUtils.getIncompleteTransferList(client.getDatadir());
        } catch(Exception e) {
            e.printStackTrace();
        }
        return incomplete;
    }
    @Override
    public void resume(Transfer transfer) {
        DownloadRequest request = new DownloadRequest(clientId, transfer.getId());
        request.setOffset(transfer.getOffset());
        try {
            client.download(request);
        } catch (RemoteException e) {
            System.err.println("Error resuming transfer: " + transfer);
        }
    }
    @Override
    public void clearIncompleteTransferList() {
        TransferUtils.removeAllIncompleteTransfers(client.getDatadir());
    }
    @Override
    public List<File> getLocalFileList() {
        return FssUtils.getFileList(client.getDatadir());
    }
    /**
     * Get the wrapped file service client.
     * @return the client
     */
    public FssCommandLineClient getFileServiceClient() {
        return client;
    }
}
